﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using System.ComponentModel;

namespace BattleforgeAssault
{
    public partial class GameView : UserControl
    {
        private Controller _controller;

        private Player _player;
        private Player _opponent;

        private LocationInfo _locations = new LocationInfo() { ScreenWidth = 1280, ScreenHeight = 800, BarWidth = 80, InfoWidth = 400 };

        public GameView()
        {
            Messager.UIDispatcher = this.Dispatcher;
            Messager.MessageEvent += OnMessageEvent;

            InitializeComponent();

            _controller = new Controller(this);
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            _controller.Start();

            // TODO: is this always player 0?
            _player = _controller.Game.Players[0];
            _opponent = _player.Opponents.FirstOrDefault();

            this.DataContext = _controller.Game;

            LayoutCards();

            Messager.SendMessage("Game Initialized");
        }

        public void CreateCardViews()
        {
            foreach (var card in _controller.Game.Cards)
            {
                CardView cardView = new CardView() { DataContext = card };
                card.View = cardView;
                CardLayer.Children.Add(cardView);
                Canvas.SetLeft(cardView, _locations.ScreenWidth / 2);
                Canvas.SetTop(cardView, _locations.ScreenHeight);
                card.PropertyChanged += OnCardPropertyChanged;
            }
        }

        void OnCardPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Location")
            {
                LayoutCards();
            }
        }

        public void LayoutCards()
        {
            LayoutCards(_opponent.Kingdom, _locations.OpponentKingdomX, _locations.OpponentKingdomY, _locations.OpponentInPlayWidth);
            LayoutCards(_opponent.Battlefield, _locations.OpponentBattlefieldX, _locations.OpponentBattlefieldY, _locations.OpponentInPlayWidth);
            LayoutCards(_opponent.Quest, _locations.OpponentQuestX, _locations.OpponentQuestY, _locations.OpponentInPlayWidth);

            LayoutCards(_controller.Game.Table, _locations.TableX, _locations.TableY, _locations.ScreenWidth);

            LayoutCards(_player.Kingdom, _locations.PlayerKingdomX, _locations.PlayerKingdomY, _locations.PlayerInPlayWidth);
            LayoutCards(_player.Battlefield, _locations.PlayerBattlefieldX, _locations.PlayerBattlefieldY, _locations.PlayerInPlayWidth);
            LayoutCards(_player.Quest, _locations.PlayerQuestX, _locations.PlayerQuestY, _locations.PlayerInPlayWidth);

            //LayoutCards(_player.Hand, _locations.PlayerOutOfPlayX, _locations.PlayerOutOfPlayY, _locations.PlayerOutOfPlayWidth);
            LayoutCards(_player.Hand, _locations.PlayerOutOfPlayX + 328, _locations.PlayerOutOfPlayY, _locations.ScreenWidth - (_locations.PlayerOutOfPlayX + 328));
            LayoutCards(_player.Deck, 0, _locations.PlayerOutOfPlayY, 160);
            LayoutCards(_player.Discard, 164, _locations.PlayerOutOfPlayY, 160);
        }

        private void LayoutCards(Location location, double x, double y, double width)
        {
            double cardWidth = 107 + 4;
            double cardHeight = 150 + 4;
            double margin = 4;

            x += margin;
            y += margin;
            width -= margin * 2;

            double spacing = (width - cardWidth) / (location.Cards.Count() - 1);
            foreach (var card in location.Cards)
            {
                CardView cardView = card.View;

                Util.PlayDoubleAnimation(Canvas.GetLeft(cardView), x, 1, cardView, Canvas.LeftProperty);
                Util.PlayDoubleAnimation(Canvas.GetTop(cardView), y, 1, cardView, Canvas.TopProperty);

                x += spacing;
            }
        }

        void OnMessageEvent(object sender, MessageEventArgs e)
        {
            if (messageList != null)
            {
                var textColor = new SolidColorBrush(Color.FromArgb(255, 105, 105, 105));
                if (e.Message.StartsWith("ERROR")) { textColor = new SolidColorBrush(Color.FromArgb(255, 220, 20, 60)); }
                string message = string.Format("{0}: {1}", messageList.Items.Count, e.Message);
                var textBlock = new TextBlock() { Text = message, Foreground = textColor };
                messageList.Items.Insert(0, textBlock);
            }
            else
            {
                Debug.WriteLine(e.Message);
            }
        }

        private void OnQueryAnswered(object sender, RoutedEventArgs e)
        {
            _controller.AnswerQuery();
        }

        private void OnTargetsSelected(object sender, RoutedEventArgs e)
        {
            _controller.ReturnTargets();
        }

        private void OnScreenSizeChanged(object sender, SizeChangedEventArgs e)
        {
            _locations.ScreenWidth = e.NewSize.Width;
            _locations.ScreenHeight = e.NewSize.Height;
            LayoutCards();
        }
    } // GameView class

    #region Helper Classes

    /// <summary>
    /// Info collection for all the game's zones. Used to place cards.
    /// </summary>
    public class LocationInfo
    {
        public double ScreenWidth { get; set; }
        public double ScreenHeight { get; set; }

        public double BarWidth { get; set; }
        public double InfoWidth { get; set; }

        public double ZoneHeight { get { return ScreenHeight / 4; } }

        public double OpponentKingdomX { get { return BarWidth; } }
        public double OpponentKingdomY { get { return 0; } }
        public double OpponentBattlefieldX { get { return BarWidth + OpponentInPlayWidth; } }
        public double OpponentBattlefieldY { get { return 0; } }
        public double OpponentQuestX { get { return BarWidth + (OpponentInPlayWidth * 2); } }
        public double OpponentQuestY { get { return 0; } }
        public double OpponentInPlayWidth { get { return (ScreenWidth - BarWidth) / 3; } }

        public double OpponentOutOfPlayX { get { return BarWidth; } }
        public double OpponentOutOfPlayY { get { return 0; } }
        public double OpponentOutOfPlayWidth { get { return ScreenWidth - BarWidth; } }

        public double TableX { get { return InfoWidth; } }
        public double TableY { get { return ZoneHeight; } }

        public double PlayerKingdomX { get { return 0; } }
        public double PlayerKingdomY { get { return ZoneHeight * 2; } }
        public double PlayerBattlefieldX { get { return PlayerInPlayWidth; } }
        public double PlayerBattlefieldY { get { return ZoneHeight * 2; } }
        public double PlayerQuestX { get { return PlayerInPlayWidth * 2; } }
        public double PlayerQuestY { get { return ZoneHeight * 2; } }
        public double PlayerInPlayWidth { get { return ScreenWidth / 3; } }

        public double PlayerOutOfPlayX { get { return BarWidth; } }
        public double PlayerOutOfPlayY { get { return ZoneHeight * 3; } }
        public double PlayerOutOfPlayWidth { get { return ScreenWidth - BarWidth; } }
    }

    #endregion Helper Classes

} // Namespace